#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int digit(int m) // digit用于计算一个整数的位数。通过不断的将整数整除以10，来确定位数。
{
  int k = 1;
  while (m /= 10)
  {
    k++; // k记录位数
  }
  return k;
}
int main(int argc, char *argv[])
{
  int n, m, i, j, max = 0, Y = 1, num; // n为输入的整数个数，m为位数，i，j为数组的下标，Y为10的位数，num为数组的元素。
  int arr[101], barrel[10][101];       // arr为输入的整数数组，barrel为一个二维数组，用于存储每个数字在当前位数上的出现次数和对应的整数
  scanf("%d", &n);
  for (i = 0; i < n; i++)
  {
    scanf("%d", &arr[i]);
    if (arr[i] > max)
      max = arr[i]; // 读取过程中同时更新max变量，以便后面确定最大位数
  }
  for (i = 0; i < digit(max); i++)     // 从最低位开始到最高位，依次进行基数排序
  {                                    // 每次排序都会将数组arr中的整数按照当前位数上的数字放入对应的桶中。
    memset(barrel, 0, sizeof(barrel)); // memset函数将二维数组barrel清零，以便下一次排序使用
    for (j = 0; j < n; j++)
    {
      num = arr[j] / Y % 10;                  // 得到当前位数上的数字num。
      barrel[num][++barrel[num][0]] = arr[j]; // 然后将这个整数放入对应的桶中，并更新桶中的计数器。
    }

    int len = 0;
    for (m = 0; m < 10; m++) // 双循环将桶中的数据按照顺序转移到数组arr中。外层遍历每个桶
    {
      for (j = 1; j <= barrel[m][0]; j++) // 内层遍历每个整数，并将它们按顺序放入数组arr中
      {
        arr[len++] = barrel[m][j];
      }
    }
    Y *= 10; // 权重Y乘以10，用于下一次的基数排序。
  }
  for (i = 0; i < n; i++)
  {
    printf("%d ", arr[i]);
  }
  return 0;
}
